package com.nut.lmsc.service.impl;

import com.nut.lmsc.cache.Cache;
import com.nut.lmsc.common.FailMessage;
import com.nut.lmsc.redis.RedisKeys;
import com.nut.lmsc.common.Result;
import com.nut.lmsc.enums.SmsEnum;
import com.nut.lmsc.service.SmsService;
import com.nut.lmsc.util.RegexUtil;
import com.nut.lmsc.util.SmsUtil;
import com.nut.lmsc.util.StringTool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class SmsServiceImpl implements SmsService {

    @Autowired
    private Cache cache;

    @Autowired
    private SmsUtil smsUtil;

    @Override
    public Result sendVerifyCode(String mobile, SmsEnum smsEnum) {

        if (StringTool.isEmpty(mobile) || !RegexUtil.isMobileExact(mobile)) {
            return Result.fail("手机号格式错误！");
        }

        String countKey = RedisKeys.getSmsCountMobileKey(mobile);
        if (cache.incrByTTL(countKey, 1L, DAY_EXPIRE_TIME) > VERIFY_DAY_MAX_COUNT) {
            log.warn("手机号[{}]，发送次数受限, 当前发送次数配置为:{}", mobile, VERIFY_DAY_MAX_COUNT);
            return Result.fail(FailMessage.SMS_MAX_COUNT);
        }

        String code = String.valueOf(ThreadLocalRandom.current().nextInt(8999) + 1000);
        Map<String, String> param = new HashMap<>(5);
        param.put("code", code);

        Result result = smsUtil.send(mobile, smsEnum, param);
        if (result.isSuccess()) {
            cache.put(RedisKeys.getSmsCodeKey(mobile, smsEnum), code, 30L, TimeUnit.MINUTES);
        }

        return result;
    }

    @Override
    public Result validVerifyCode(String mobile, String code, SmsEnum smsEnum) {

        String key = RedisKeys.getSmsCodeKey(mobile, smsEnum);
        Object object = cache.get(key);
        if (object == null) {
            return Result.fail(FailMessage.BAD_ARGUMENT);
        }
        // 检查短信验证码是否正确
        if (!object.toString().equals(code)) {
            return Result.fail(FailMessage.WRONG_CODE_ARGUMENT);
        }

        return Result.ok();
    }


}
